package orm

import (
	"strings"

	"gitee.com/xiawucha365/sago.v2/core/config"
	"gopkg.in/mgo.v2"
)

type DbMongodb struct {
	Db
	cf *config.Config
}

func NewDbMongo(cf *config.Config, engine ...DbEngineName) *DbMongodb {

	dbmongo := &DbMongodb{}
	dbmongo.cf = cf
	//设置优先
	if len(engine) > 0 {
		if _, ok := orms[engine[0]]; ok {
			dbmongo.engineType = orms[DbEngineName(cf.Mongodb.Engine)]
		}
		//配置
	} else if cf.Mysql.Engine != "" {
		if _, ok := orms[DbEngineName(cf.Mongodb.Engine)]; ok {
			dbmongo.engineType = orms[DbEngineName(cf.Mongodb.Engine)]
		}
	}

	dbmongo.initMongoDb(cf)

	return dbmongo
}

func (dbm *DbMongodb) initMongoDb(cf *config.Config) {
	switch dbm.engineType {
	case DbMongoEngineTypeMgo:
		dbm.Engine.Mgo = newDbMongoMgoByConfig(cf)
	default:
		dbm.Engine.Mgo = newDbMongoMgoByConfig(cf)
	}
}

func (dbm *DbMongodb) Close() {
	switch dbm.engineType {
	case DbMongoEngineTypeMgo:
		dbm.Engine.Mgo.Session.Close()
	default:
		dbm.Engine.Mgo.Session.Close()
	}
}

func newDbMongoMgoByConfig(cf *config.Config) *EngineMgo {
	var addr string
	if len(cf.Mongodb.Addrs) == 1 {
		addr = "mongodb://" + cf.Mongodb.Username + ":" + cf.Mongodb.Password + "@" + cf.Mongodb.Addrs[0]

	} else if len(cf.Mongodb.Addrs) > 1 {
		addr = "mongodb://" + cf.Mongodb.Username + ":" + cf.Mongodb.Password + "@" + strings.Join(cf.Mongodb.Addrs, ",") +
			"?replicaSet=" + cf.Mongodb.ReplicaSet + "&authSource=" + cf.Mongodb.Dbname
	} else {
		return nil
	}
	return createMgo(addr, cf.Mongodb.Dbname)
}

//直接操作db
func GetMongodbConnByDb(cf *config.Config, engine DbEngineName, dbname string) *DbMongodb {
	cf.Mongodb.Dbname = dbname
	return NewDbMongo(cf, engine)
}

//通过addr链接
func GetMongodbConnByAddr(cf *config.Config, engine DbEngineName, addr string) *DbMongodb {
	db := NewDbMongo(cf, engine)
	switch db.engineType {
	case DbMysqlEngineTypeXorm:
		db.Engine.Mgo = createMgo(addr, cf.Mongodb.Dbname)
	default:
		db.Engine.Mgo = createMgo(addr, cf.Mongodb.Dbname)
	}
	return db

}

//op

func (dbm *DbMongodb) Upsert(clname string, selector interface{}, update interface{}) (interface{}, error) {
	if dbm.engineType == DbMongoEngineTypeMgo {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Upsert(selector, update)
	} else {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Upsert(selector, update)
	}
}

func (dbm *DbMongodb) Update(clname string, selector interface{}, update interface{}) error {

	if dbm.engineType == DbMongoEngineTypeMgo {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Update(selector, update)
	} else {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Update(selector, update)
	}
}

func (dbm *DbMongodb) Insert(clname string, docs ...interface{}) error {
	if dbm.engineType == DbMongoEngineTypeMgo {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Insert(docs...)
	} else {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Insert(docs...)
	}
}

func (dbm *DbMongodb) Find(clname string, query interface{}) *mgo.Query {
	if dbm.engineType == DbMongoEngineTypeMgo {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Find(query)
	} else {
		cl := dbm.Engine.Mgo.Session.DB(dbm.cf.Mongodb.Dbname).C(clname)
		return cl.Find(query)
	}
}
